package fun.mashuai.generator.plugins.core;

import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;
import org.mybatis.generator.codegen.mybatis3.xmlmapper.elements.AbstractXmlElementGenerator;

import java.util.List;

/**
 * @author 马帅
 * @version 1.0
 * @className CustomAbstractXmlElementGenerator.java
 * @description TODO
 * @date 2020/4/18 23:36
 */
public class CustomAbstractXmlElementGenerator extends AbstractXmlElementGenerator {

    @Override
    public void addElements(XmlElement parentElement) {

        addSqlBaseCondition(parentElement);
        addSelectCountByCondition(parentElement);
        addSelectByCondition(parentElement);
        addBatchUpdate(parentElement);
    }


    /**
     * 公用sql include
     */
    private void addSqlBaseCondition(XmlElement parentElement) {
        // 增加 Base_Condition_List
        XmlElement sql = new XmlElement("sql");
        sql.addAttribute(new Attribute("id", "Base_Condition_List"));

        //在这里添加where条件
        XmlElement selectTrimElement = new XmlElement("trim");
        selectTrimElement.addAttribute(new Attribute("prefix", "WHERE"));
        selectTrimElement.addAttribute(new Attribute("prefixOverrides", "AND |OR "));

        StringBuilder sb = new StringBuilder();

        for(IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
            XmlElement selectNotNullElement = new XmlElement("if");
            sb.setLength(0);
            sb.append(introspectedColumn.getJavaProperty()).append(" != null");
            // 日期时间不能判断空字符
            if(!"TIMESTAMP".equals(introspectedColumn.getJdbcTypeName())){
                sb.append(" and ").append(introspectedColumn.getJavaProperty()).append(" != '' ");
            }

            selectNotNullElement.addAttribute(new Attribute("test", sb.toString()));

            sb.setLength(0);
            sb.append("and ");
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            // 添加等号
            sb.append(" = ");
            sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn));

            selectNotNullElement.addElement(new TextElement(sb.toString()));
            selectTrimElement.addElement(selectNotNullElement);
        }
        sb.setLength(0);
        sql.addElement(selectTrimElement);
        parentElement.addElement(sql);
    }

    /**
     * 条件统计
     */
    private void addSelectCountByCondition(XmlElement parentElement) {
        XmlElement select = new XmlElement("select");
        select.addAttribute(new Attribute("id", "countByCondition"));
        select.addAttribute(new Attribute("resultType", "java.lang.Integer"));
        select.addAttribute(new Attribute("parameterType", introspectedTable.getBaseRecordType()));

        StringBuilder sb = new StringBuilder();
        sb.setLength(0);
        sb.append("select count(*) from ");
        sb.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());

        // 公用include
        XmlElement include = new XmlElement("include");
        include.addAttribute(new Attribute("refid", "Base_Condition_List"));

        select.addElement(new TextElement(sb.toString()));
        select.addElement(include);
        parentElement.addElement(select);
    }

    /**
     * 条件查询
     */
    private void addSelectByCondition(XmlElement parentElement) {
        XmlElement select = new XmlElement("select");
        select.addAttribute(new Attribute("id", "selectByCondition"));
        select.addAttribute(new Attribute("resultMap", "BaseResultMap"));
        select.addAttribute(new Attribute("parameterType", introspectedTable.getBaseRecordType()));

        StringBuilder sb = new StringBuilder();
        sb.setLength(0);
        sb.append("select ");
        select.addElement(new TextElement(sb.toString()));

        // Base_Column_List include
        XmlElement baseColumnListInclude = new XmlElement("include");
        baseColumnListInclude.addAttribute(new Attribute("refid", "Base_Column_List"));
        select.addElement(baseColumnListInclude);

        sb.setLength(0);
        sb.append("from ");
        sb.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
        select.addElement(new TextElement(sb.toString()));

        // 公用include
        XmlElement baseConditionListInclude = new XmlElement("include");
        baseConditionListInclude.addAttribute(new Attribute("refid", "Base_Condition_List"));
        select.addElement(baseConditionListInclude);

        XmlElement ifElement = new XmlElement("if");
        sb.setLength(0);
        sb.append("orderByClause != null and orderByClause != '' ");
        ifElement.addAttribute(new Attribute("test", sb.toString()));

        sb.setLength(0);
        sb.append(" order by ${orderByClause}");
        ifElement.addElement(new TextElement(sb.toString()));
        select.addElement(ifElement);


        parentElement.addElement(select);
    }
    /**
     * 批量更新
     */
    private void addBatchUpdate(XmlElement parentElement) {
        XmlElement updateXml = new XmlElement("update");
        updateXml.addAttribute(new Attribute("id", "batchUpdate"));
        updateXml.addAttribute(new Attribute("parameterType", "java.util.List"));

        StringBuilder sb = new StringBuilder();
        sb.setLength(0);
        sb.append("update ");
        sb.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
        updateXml.addElement(new TextElement(sb.toString()));

        XmlElement trimXml = new XmlElement("trim");
        trimXml.addAttribute(new Attribute("prefix", "set"));
        trimXml.addAttribute(new Attribute("suffixOverrides", ","));

        for(IntrospectedColumn column : introspectedTable.getAllColumns()) {
            XmlElement trimXml1 = new XmlElement("trim");
            trimXml1.addAttribute(new Attribute("prefix", column.getActualColumnName() + " = case"));
            trimXml1.addAttribute(new Attribute("suffix", "end,"));

            XmlElement foreachXml = new XmlElement("foreach");
            foreachXml.addAttribute(new Attribute("collection", "list"));
            foreachXml.addAttribute(new Attribute("item", "item"));
            foreachXml.addAttribute(new Attribute("index", "index"));


            XmlElement ifXml = new XmlElement("if");
            sb.setLength(0);
            sb.append("item.");
            sb.append(column.getJavaProperty());
            sb.append(" != null");
            // 日期时间不能判断空字符
            if(!"TIMESTAMP".equals(column.getJdbcTypeName())){
                sb.append(" and ");
                sb.append("item.");
                sb.append(column.getJavaProperty());
                sb.append(" != '' ");
            }

            ifXml.addAttribute(new Attribute("test", sb.toString()));

            sb.setLength(0);
            sb.append("when ");
            sb.append(introspectedTable.getPrimaryKeyColumns().get(0).getActualColumnName());
            sb.append(" = ");
            sb.append("#{item.");
            sb.append(introspectedTable.getPrimaryKeyColumns().get(0).getJavaProperty());
            sb.append("}");
            sb.append(" then ");
            sb.append("#{item.");
            sb.append(column.getJavaProperty());
            sb.append("}");

            ifXml.addElement(new TextElement(sb.toString()));
            foreachXml.addElement(ifXml);
            trimXml1.addElement(foreachXml);

            trimXml.addElement(trimXml1);
        }

        updateXml.addElement(trimXml);

        sb.setLength(0);
        sb.append("where ");
        sb.append(introspectedTable.getPrimaryKeyColumns().get(0).getActualColumnName());
        sb.append(" in ");
        updateXml.addElement(new TextElement(sb.toString()));

        XmlElement foreachXml1 = new XmlElement("foreach");
        foreachXml1.addAttribute(new Attribute("collection", "list"));
        foreachXml1.addAttribute(new Attribute("item", "item"));
        foreachXml1.addAttribute(new Attribute("index", "index"));
        foreachXml1.addAttribute(new Attribute("separator", ","));
        foreachXml1.addAttribute(new Attribute("open", "("));
        foreachXml1.addAttribute(new Attribute("close", ")"));

        sb.setLength(0);
        sb.append("#{item.");
        sb.append(introspectedTable.getPrimaryKeyColumns().get(0).getJavaProperty());
        sb.append(", ");
        sb.append("jdbcType=BIGINT}");
        foreachXml1.addElement(new TextElement(sb.toString()));

        updateXml.addElement(foreachXml1);
        parentElement.addElement(updateXml);
    }
}
